{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "1a9dbd4b",
   "metadata": {},
   "source": [
    "# VCOM窗口烧录——黄金分割搜索"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c0a8b8ba",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "第一次执行：初始化JEITA mode\n",
      "0x31 43.26949\n",
      "0x4e 12.56823\n",
      "0x1e 15.46334\n",
      "0x3c 20.9813\n",
      "0x29 22.38634\n",
      "0x35 30.9434\n",
      "0x2e 29.65835\n",
      "0x32 52.02091\n",
      "0x33 39.42044\n",
      "best reg: 0x32 0x64 best JEITA: 52.02091 call times 9\n"
     ]
    }
   ],
   "source": [
    "from OpticalSensor import CA410Sensor as EyeSensor\n",
    "#from f500 import EyeSensor\n",
    "import numpy as np, time\n",
    "import jtoollib as jt\n",
    "\n",
    "from pic_window import *\n",
    "\n",
    "import OperateCardLib\n",
    "\n",
    "# D-VCOM取值范围，0x00->0x7F， 末位0为MTP，1为DAC\n",
    "\n",
    "\n",
    "sensor = EyeSensor(port='COM13')\n",
    "\n",
    "dll_path = \"./OperateCardLib.dll\"\n",
    "card_lib = OperateCardLib.Nova_NT71877(dll_path)\n",
    "\n",
    "# Initialize the card\n",
    "# CardID是以下值;intel_edp:0   intel_dp:1   amd_edp:2   nvidia:3  Qualcomm:5  amd_dp:6\n",
    "card_lib.init(6)\n",
    "\n",
    "\n",
    "\n",
    "win = NonBlockingImageWindow(\"Demo\", size=(400, 400), fps=10)\n",
    "img = np.zeros((400, 400, 3), dtype=np.uint8)\n",
    "img[:, 0:400:2, 1] = 127\n",
    "\n",
    "win.update(img, fmt=\"rgb\")\n",
    "\n",
    "# 只在第一次运行时执行\n",
    "if 'JETA_flag' not in globals():\n",
    "    print(\"第一次执行：初始化JEITA mode\")\n",
    "    sensor.JETAmode()\n",
    "    JETA_flag = True\n",
    "else:\n",
    "    print(\"已进入Jeita mode。\")\n",
    "\n",
    "\n",
    "\n",
    "def get_data(x):\n",
    "    card_lib.write_vcom(x<<1)\n",
    "    temp = sensor.GetJETA()\n",
    "    print(hex(x), temp)\n",
    "    return temp\n",
    "\n",
    "\n",
    "import math\n",
    "\n",
    "def argmax_golden_int(f, lo, hi, *, max_calls=None):\n",
    "    \"\"\"\n",
    "    在闭区间 [lo, hi] 的整数上，使用整数黄金分割搜索最大化 f(x)。\n",
    "    适用前提：f 在区间内近似单峰（unimodal）。\n",
    "    每轮仅新增一次函数采样；内部做了 memo 缓存避免重复调用。\n",
    "\n",
    "    返回: (best_x, best_val, calls)\n",
    "    \"\"\"\n",
    "    assert isinstance(lo, int) and isinstance(hi, int) and lo <= hi\n",
    "    phi_inv = (math.sqrt(5) - 1) / 2  # ≈ 0.618\n",
    "    cache = {}\n",
    "\n",
    "    def F(x):\n",
    "        if x not in cache:\n",
    "            cache[x] = f(x)\n",
    "        return cache[x]\n",
    "\n",
    "    if lo == hi:\n",
    "        return lo, F(lo), 1\n",
    "\n",
    "    # 初始两个内点（向整数对齐），保证 lo <= m1 < m2 <= hi\n",
    "    h = hi - lo\n",
    "    m1 = hi - int(round(phi_inv * h))\n",
    "    m2 = lo + int(round(phi_inv * h))\n",
    "    if m1 == m2:\n",
    "        # 退一步，确保两个点不同\n",
    "        if m2 < hi: m2 += 1\n",
    "        elif m1 > lo: m1 -= 1\n",
    "    m1 = max(lo, min(m1, hi))\n",
    "    m2 = max(lo, min(m2, hi))\n",
    "    if m1 > m2:\n",
    "        m1, m2 = m2, m1\n",
    "\n",
    "    f1, f2 = F(m1), F(m2)\n",
    "    calls_limit = float('inf') if max_calls is None else max_calls\n",
    "\n",
    "    # 主循环：每次只新增一个点的评估\n",
    "    while hi - lo > 3 and len(cache) < calls_limit:\n",
    "        if f1 < f2:           # 寻找最大值：右侧更高 -> 丢弃左段\n",
    "            lo = m1\n",
    "            m1, f1 = m2, f2   # 复用\n",
    "            h = hi - lo\n",
    "            m2 = lo + int(round(phi_inv * h))\n",
    "            if m2 == m1:      # 避免重复点\n",
    "                m2 = min(hi, m2 + 1)\n",
    "            f2 = F(m2)\n",
    "        else:                 # 左侧更高 -> 丢弃右段\n",
    "            hi = m2\n",
    "            m2, f2 = m1, f1   # 复用\n",
    "            h = hi - lo\n",
    "            m1 = hi - int(round(phi_inv * h))\n",
    "            if m1 == m2:\n",
    "                m1 = max(lo, m1 - 1)\n",
    "            f1 = F(m1)\n",
    "\n",
    "    # 收尾：区间很小时，暴力枚举（至多 4 个点），只补未算过的\n",
    "    best_x, best_v = None, -float('inf')\n",
    "    for x in range(lo, hi + 1):\n",
    "        v = F(x)\n",
    "        if v > best_v:\n",
    "            best_x, best_v = x, v\n",
    "    return best_x, best_v, len(cache)\n",
    "\n",
    "\n",
    "\n",
    "try:\n",
    "    best_x, best_val, calls = argmax_golden_int(get_data, 0x00, 0x7F)\n",
    "    print(\"best reg:\",hex(best_x), hex(best_x<<1), \"best JEITA:\",best_val, \"call times\", calls)\n",
    "    card_lib.write_vcom(best_x<<1)\n",
    "\n",
    "finally:\n",
    "    del card_lib\n",
    "    win.stop()\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a7a79283",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
